package com.rfid.util;

import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.module.interaction.ModuleConnector;
import com.rfid.RFIDReaderHelper;
import com.rfid.ReaderConnector;
import com.rfid.config.CMD;
import com.rfid.config.ERROR;
import com.rfid.db.bean.Rfid;
import com.rfid.jni.RfidDecoder;
import com.rfid.rls_psw.R;
import com.rfid.rxobserver.RXObserver;
import com.rfid.rxobserver.ReaderSetting;
import com.rfid.rxobserver.bean.RXInventoryTag;
import com.rfid.rxobserver.bean.RXOperationTag;
import com.util.StringTool;

import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;

public class RfidManager {

    private static final String TAG = "RfidManager";
    private RFIDReaderHelper mReaderHelper;
    private static ModuleConnector connector = new ReaderConnector();
    private int baud = 115200;
    private Context mContent;
    private boolean mIsLoop = false;
    private long mStartTime;
    private long mTotalTime;
    private boolean isConnect;
    private static RfidManager mRfidManager;
    RfidDecoder mrRfidDecoder = new RfidDecoder();

    private ReaderSetting m_curReaderSetting;

    private int btReadId = -1;

    private RfidListener mRfidListener;

    private boolean decodeEpc = false;

    public static RfidManager getInstance() {
        if(mRfidManager == null) {
            mRfidManager = new RfidManager();
        }
        return mRfidManager;
    }

    public void setRfidListener(RfidListener listener) {
        mRfidListener = listener;
    }

    public void setDecodeEpcEnable(boolean decode) {
        System.out.println("setDecodeEpcEnable decode = " + decode);
        this.decodeEpc = decode;
    }

    private void notityOutPutPower() {
        if (m_curReaderSetting.btAryOutputPower != null && mRfidListener != null) {
            mRfidListener.onOutputPower(m_curReaderSetting.btAryOutputPower[0] & 0xFF);
        }
    }

    public RfidManager() {
        try {
            mReaderHelper = RFIDReaderHelper.getDefaultHelper();
            m_curReaderSetting = ReaderSetting.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void getOutputPower() {
        System.out.println("getOutputPower");
        mReaderHelper.getOutputPower(m_curReaderSetting.btReadId);
    }

    public void setOutputPower(int power) {
        System.out.println("setOutputPower power = " + power);
        mReaderHelper.setOutputPower(m_curReaderSetting.btReadId, (byte) power);
        m_curReaderSetting.btAryOutputPower = new byte[]{(byte) power};
    }

    public void start() {
        if(!isConnect) {
            Log.w(TAG,"please connect first!");
            return;
        }
        mIsLoop = true;
        mLoopRunnable.run();
    }

    public void stop() {
        mIsLoop = false;
    }

    public void quit() {
        mIsLoop = false;
        set53CGPIOEnabled(false);
        if(isConnect) {
            connector.disConnect(mContent);
        }
        isConnect = false;
    }

    public void connect(Context context) {
        mContent = context.getApplicationContext();
        try {
            set53CGPIOEnabled(true);
            SystemClock.sleep(150);
            Log.e(TAG,"set53CGPIOEnabled");
            if (connector.connectCom("/dev/ttyHSL0", baud,mContent)) {
                Log.e(TAG,"connectCom: success");
                mReaderHelper.registerObserver(mObserver);
                mReaderHelper.startWith();
                isConnect = true;
            }
        } catch (SecurityException e) {
            Toast.makeText(
                    mContent,
                    mContent.getResources().getString(R.string.error_security),
                    Toast.LENGTH_SHORT).show();
        }
        catch (InvalidParameterException e) {
            Toast.makeText(
                    mContent,
                    mContent.getResources().getString(R.string.error_configuration),
                    Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void set53CGPIOEnabled(boolean enable){
        FileOutputStream f = null;
        FileOutputStream f1 = null;
        try{
            Log.i("urovo","enable:"+enable);
            f = new FileOutputStream("/sys/devices/soc/soc:sectrl/ugp_ctrl/gp_pogo_5v_ctrl/enable");
            f.write(enable?"1".getBytes():"0".getBytes());
            f1 = new FileOutputStream("/sys/devices/soc/soc:sectrl/ugp_ctrl/gp_otg_en_ctrl/enable");
            f1.write(enable?"1".getBytes():"0".getBytes());

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(f != null){
                try {
                    f.close();
                    f1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private RXObserver mObserver = new RXObserver() {

        @Override
        protected void onInventoryTag(RXInventoryTag tag) {
            System.out.println("onInventoryTag strEPC = " + tag.strEPC + ",tag.strPC = " + tag.strPC + ",tag.strRSSI = " +tag.strRSSI + ",tag.strFreq = " + tag.strFreq);
            if(!mIsLoop) {
                return;
            }
            try {
                String hex = tag.strEPC.replace(" ", "").trim();
                System.out.println(hex);//E200001918190052195017B6崩溃,010200A118030000C4000000正常
                BeeperUtils.beep(BeeperUtils.BEEPER_SHORT);
                if(!decodeEpc) {
                    if(mRfidListener != null) {
                        mRfidListener.onRfid(hex);
                    }
                    return;
                }
                LogUtils.v("hex = " +hex);
                hex = hex.substring(4 * 2, hex.length());
                System.out.println(hex + "<>" + hex.length());
                byte data[] = Util.hexStr2bytes(hex);
                int r = 0;
                System.out.println("data len = " + data.length);
                if (hex.length() > 16) {
                    System.out.println("iRFID_Decode128bit");
                    r = mrRfidDecoder.iRFID_Decode128bit(data);
                } else {
                    System.out.println("iRFID_Decode96bit");
                    r = mrRfidDecoder.iRFID_Decode96bit(data);
                }
                System.out.println("result = " + new String(data).trim() + "---" + r);
                if(r > 0 && mRfidListener != null) {
                    mRfidListener.onRfid(new String(data).trim());
                }
                r = mrRfidDecoder.iRFID_Encode96bit(data);
                System.out.println(Util.bytesToHexString(data) + "===========" + r);

                r = mrRfidDecoder.iRFID_Decode96bit(data);
                System.out.println(new String(data).trim() + "===++++===" + r);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void onInventoryTagEnd(final RXInventoryTag.RXInventoryTagEnd tagEnd) {
//            System.out.println("onInventoryTagEnd tagEnd.cmd = " + tagEnd.cmd + ",tagEnd.mReadRate = " + tagEnd.mReadRate);
            long exeTime = System.currentTimeMillis() - mStartTime;
            mTotalTime += exeTime;
            if (mIsLoop) {
                mLoopRunnable.run();
            }
            BeeperUtils.beep(BeeperUtils.BEEPER);
        }

        @Override
        protected void onExeCMDStatus(final byte cmd, final byte status) {
            mLoopHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mIsLoop) {
                        if (cmd == CMD.CUSTOMIZED_SESSION_TARGET_INVENTORY || cmd == CMD.REAL_TIME_INVENTORY) {
                            mLoopRunnable.run();
                        }
                    }
                    if (cmd == CMD.GET_OUTPUT_POWER || cmd == CMD.SET_OUTPUT_POWER) {
                        System.out.println("GET_OUTPUT_POWER");
                        notityOutPutPower();
                    }
                    if(status != ERROR.SUCCESS) {
                        LogUtils.v("onExeCMDStatus status = " + status + ",cmd = " + cmd);
                    } else {
                        LogUtils.v("onExeCMDStatus success");
                    }
                }
            });
        }

        @Override
        protected void onOperationTag(RXOperationTag tag) {
            super.onOperationTag(tag);
            LogUtils.v("onOperationTag tag.strEPC, = " + tag.strEPC);
            if(mRfidListener != null) {
                String hex = tag.strEPC.replace(" ","").trim();
                if(mRfidListener != null) {
                    mRfidListener.onOperationTag(hex.trim());
                }
            }
        }
    };

    public void writeEpc(String epc) {
        LogUtils.v("writeEpc epc = " + epc);
        byte data[] = epc.trim().getBytes();
        int r = mrRfidDecoder.iRFID_Encode96bit(data);
        LogUtils.v("encode96it r = " + r + "---" + Util.bytesToHexString(data));
        byte btMemBank = 0x01;
        byte btWordAdd = 0x02;
        byte btWordCnt = 0x00;
        byte[] btAryData = null;
        String[] result = null;
        byte[] btAryPassWord = null;
        try {
            epc = "00000000" + Util.bytesToHexString(data).trim();//前面四个字节不要了，解析规则就是这么定义的。
            String[] reslut = StringTool.stringToStringArray("00000000", 2);
            btAryPassWord = StringTool.stringArrayToByteArray(reslut, 4);
        } catch (Exception e) {
            LogUtils.v("RfManager","密码格式错误1");
            return;
        }
        try {
            result = StringTool.stringToStringArray(epc.toUpperCase(), 2);
            btAryData = StringTool.stringArrayToByteArray(result, result.length);
            btWordCnt = (byte) ((result.length / 2 + result.length % 2) & 0xFF);
        } catch (Exception e) {
            LogUtils.v("RfManager","写入格式错误1 epc = " + epc);
            return;
        }
        if (btAryData == null || btAryData.length <= 0) {
            LogUtils.v("RfManager","写入格式错误");
            return;
        }
        StringBuffer sb = new StringBuffer();
        for(String s : result) {
            sb.append(s);
        }
        LogUtils.v("begain writeEpc epc = " + epc+ ",btWordCnt = " + btWordCnt + ",result = " + sb.toString());
        mReaderHelper.writeTag(m_curReaderSetting.btReadId, btAryPassWord, btMemBank, btWordAdd, btWordCnt, btAryData);
    }

    public void writeLevel(String barcode) {
        String epc = RfidUitl.encodeLevelBarcode(barcode);
        if(TextUtils.isEmpty(epc)) {
            return;
        }
        byte btMemBank = 0x01;
        byte btWordAdd = 0x02;
        byte btWordCnt = 0x00;
        byte[] btAryData = null;
        String[] result = null;
        byte[] btAryPassWord = null;
        try {
            String[] reslut = StringTool.stringToStringArray("00000000", 2);
            btAryPassWord = StringTool.stringArrayToByteArray(reslut, 4);
        } catch (Exception e) {
            LogUtils.v("RfManager","密码格式错误1");
            return;
        }
        try {
            result = StringTool.stringToStringArray(epc.toUpperCase(), 2);
            btAryData = StringTool.stringArrayToByteArray(result, result.length);
            btWordCnt = (byte) ((result.length / 2 + result.length % 2) & 0xFF);
        } catch (Exception e) {
            LogUtils.v("RfManager","写入格式错误1 epc = " + epc);
            return;
        }
        if (btAryData == null || btAryData.length <= 0) {
            LogUtils.v("RfManager","写入格式错误");
            return;
        }
        StringBuffer sb = new StringBuffer();
        for(String s : result) {
            sb.append(s);
        }
        LogUtils.v("begain writeLevel epc = " + epc+ ",btWordCnt = " + btWordCnt + ",result = " + sb.toString()+ ",btAryData len = " + btAryData.length);
        mReaderHelper.writeTag(m_curReaderSetting.btReadId, btAryPassWord, btMemBank, btWordAdd, btWordCnt, btAryData);
    }

    public void getEpc() {
        byte btMemBank = 0x01;
        byte btWordAdd = 0x02;
        byte btWordCnt = 0x06;
        byte[] btAryData = null;
        String[] result = null;
        byte[] btAryPassWord = null;
        LogUtils.v("getEpc");
        mReaderHelper.readTag(m_curReaderSetting.btReadId, btMemBank, btWordAdd, btWordCnt, btAryPassWord);
    }


    private Handler mLoopHandler = new Handler();
    private Runnable mLoopRunnable = new Runnable() {
        @Override
        public void run() {
//            System.out.println("run mIsLoop = " + mIsLoop);
            mLoopHandler.removeCallbacks(this);
            if(!mIsLoop) {
                return;
            }
            byte  addr = -1;
            mReaderHelper.customizedSessionTargetInventory(addr,
                    (byte)0x01,
                    (byte)0x00,
                    (byte)0x01);
            mLoopHandler.postDelayed(this, 2000);
            mStartTime = System.currentTimeMillis();
        }
    };


    public interface RfidListener{

        public void onRfid(String rfid);

        default public void onShelf(String shelf){}
        default public void onOutputPower(int power){}

        default public void onOperationTag(String epc){};
    }
}
